﻿/* ===============================================================================  
 * Copyright (c) 2010 Acid Frameworks
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 * =============================================================================== */

using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Acid.Math;

namespace Acid.Rendering.Collada
{
    #region Supporting Types

    public enum fx_opaque_enum
    {
        A_ONE,
        RGB_ZERO,
        UNKNOWN,
    }

    public class float4
    {
        public Vector4 value { get; set; }
    }
    public class common_float_or_param_type
    {
        public float value;

        public common_float_or_param_type()
        {
            this.value = 0.0f;
        }
    }
    public class common_color_or_texture_type
    {
        public Texture texture;
        public float4  color;

        public common_color_or_texture_type()
        {
            this.color   = null;
            this.texture = null;
        }

        public class Texture
        {
            public string texture;
            public string texcoord;

            public Texture()
            {
                this.texture  = string.Empty;
                this.texcoord = string.Empty;
            }
        }
    }
    public class common_transparent_type : common_color_or_texture_type
    {
        public fx_opaque_enum opaque;

        public common_transparent_type() : base()
        {
            this.opaque = fx_opaque_enum.UNKNOWN;
        }
    }

    #endregion


    public partial class Document
    {
        public string xmlns;
        public string version;

        public Asset                 asset;
        public LibraryAnimations     library_animations;
        public LibraryAnimationClips library_animation_clips;
        public LibraryImages         library_images;
        public LibraryLights         library_lights;
        public LibraryCameras        library_cameras;
        public LibraryMaterials      library_materials;
        public LibraryEffects        library_effects;
        public LibraryGeometries     library_geometries;
        public LibraryControllers    library_controllers;
        public LibraryVisualScenes   library_visual_scenes;
        public Scene                 scene;

        public Document()
        {
            this.asset = null;
            this.library_animations = null;
            this.library_animation_clips = null;
            this.library_images = null;
            this.library_cameras = null;
            this.library_lights = null;
            this.library_materials = null;
            this.library_effects = null;
            this.library_geometries = null;
            this.library_controllers = null;
            this.library_visual_scenes = null;
            this.scene = null;
        }

        #region Asset

        public class Asset
        {
            public Contributor contributor;
            public Unit        unit;
            public DateTime    created;
            public DateTime    modified;
            public string      up_axis;

            public Asset()
            {
                this.contributor = null;
                this.unit        = null;
            }

            public class Contributor
            {
                public string author;
                public string authoring_tool;
                public string comments;
            }
            public class Unit
            {
                public string name;
                public float meter;
            }
        }
        
        #endregion

        #region Library Animations

        public class LibraryAnimations
        {
            public List<Animation> animations;

            public LibraryAnimations()
            {
                this.animations = new List<Animation>();    
            }

            public class Animation
            {
                public string       id;
                public List<Source> sources;
                public Sampler      sampler;
                public Channel      channel;

                public Animation()
                {
                    this.id         = string.Empty;
                    this.sources    = new List<Source>();
                    this.sampler    = null;
                    this.channel    = null;
                }

                public class Source
                {
                    public string          elementType;
                    public string          id;
                    public FloatArray      float_array;
                    public NameArray       name_array;
                    public TechniqueCommon technique_common;
                    
                    public Source()
                    {
                        this.elementType      = string.Empty;
                        this.id               = string.Empty;
                        this.float_array      = null;
                        this.name_array       = null;
                        this.technique_common = null;
                    }

                    public class NameArray       
                    {
                        public string       id;
                        public int          count;
                        public List<string> values;

                        public NameArray()
                        {
                            this.id     = string.Empty;
                            this.count  = 0;
                            this.values = new List<string>();
                        }
                    }

                    public class FloatArray      
                    {
                        public string      id;
                        public int         count;
                        public List<float> values;

                        public FloatArray()
                        {
                            this.id     = string.Empty;
                            this.count  = 0;
                            this.values = new List<float>();
                        }
                    }

                    public class TechniqueCommon 
                    {
                        public Accessor accessor;

                        public TechniqueCommon()
                        {
                            this.accessor = null;
                        }

                        public class Accessor
                        {
                            public string      source;
                            public int         count;
                            public int         stride;
                            public List<Param> param_list;

                            public Accessor()
                            {
                                this.source    = string.Empty;
                                this.count     = 0;
                                this.stride    = 0;
                                this.param_list = new List<Param>();
                            }

                            public class Param
                            {
                                public string name;
                                public string type;

                                public Param()
                                {
                                    this.name = string.Empty;
                                    this.type = string.Empty;
                                }
                            }  
                        }
                    }
                }

                public class Sampler
                {
                    public string      id;
                    public List<Input> inputs;

                    public Sampler()
                    {
                        this.id        = string.Empty;
                        this.inputs = new List<Input>();
                    }
                    public class Input
                    {
                        public string semantic;
                        public string source;

                        public Input()
                        {
                            this.semantic = string.Empty;
                            this.source   = string.Empty;
                        }
                    }
                }

                public class Channel
                {
                    public string source;
                    public string target;

                    public Channel()
                    {
                        this.source = string.Empty;
                        this.target = string.Empty;
                    }
                }
            }
        }

        #endregion

        #region Library Animation Clips
  
        public class LibraryAnimationClips
        {
            public List<AnimationClip> animation_clipList;

            public LibraryAnimationClips()
            {
                this.animation_clipList = new List<AnimationClip>();
            }

            public class AnimationClip
            {
                public string id;
                public float start;
                public float end;
                public List<InstanceAnimation> instance_animations;

                public AnimationClip()
                {
                    this.id                     = string.Empty;
                    this.start                  = 0.0f;
                    this.end                    = 0.0f;
                    this.instance_animations    = new List<InstanceAnimation>();
                }

                public class InstanceAnimation
                {
                    public string url;

                    public InstanceAnimation()
                    {
                        this.url = string.Empty;
                    }
                }
            }
        }

        #endregion

        #region Library Images

        public class LibraryImages
        {
            public List<Image> images;

            public LibraryImages()
            {
                this.images = new List<Image>();
            }

            public class Image
            {
                public string id;
                public string name;
                public string init_from;

                public Image()
                {
                    this.id        = string.Empty;
                    this.name      = string.Empty;
                    this.init_from = string.Empty;
                }
            }
        }


        #endregion

        #region Library Cameras

        public class LibraryCameras
        {
            public List<Camera> cameras;

            public LibraryCameras()
            {
                this.cameras = new List<Camera>();            
            }

            public class Camera
            {
                public string id;
                public Optics optics;

                public Camera()
                {
                    this.id     = string.Empty;
                    this.optics = null;
                }
                public class Optics
                {
                    public TechniqueCommon technique_common;
                    
                    public Optics()
                    {
                        this.technique_common = null;
                    }

                    public class TechniqueCommon
                    {
                        public Perspective perspective;

                        public TechniqueCommon()
                        {
                            this.perspective = null;
                        }

                        public class Perspective
                        {
                            public float xfov;
                            public float aspect_ratio;
                            public float znear;
                            public float zfar;

                            public Perspective()
                            {
                                this.xfov         = 0.0f;
                                this.aspect_ratio = 0.0f;
                                this.znear        = 0.0f;
                                this.zfar         = 0.0f;
                            }
                        }
                    }
                }
            }
        }
        
        
        #endregion

        #region Library Lights

        public class LibraryLights
        {
            public List<Light> lights;
            
            public LibraryLights()
            {
                this.lights = new List<Light>();           
            }

            public class Light
            {
                public string          id;
                public TechniqueCommon technique_common;
                
                public Light()
                {
                    this.id               = string.Empty;
                    this.technique_common = null;
                }

                public class TechniqueCommon
                {
                    public string      elementType;
                    public Spot        spot;
                    public Point       point;
                    public Directional directional;

                    public TechniqueCommon()
                    {
                        this.elementType = string.Empty;
                        this.spot        = null;
                        this.point       = null;
                        this.directional = null;
                    }
                    public class Directional
                    {
                        public Vector3 color;

                        public Directional()
                        {
                            this.color = Vector3.Zero;
                        }
                    }

                    public class Spot
                    {
                        public Spot()
                        {
                            this.color                 = Vector3.Zero;
                            this.constant_attenuation  = 0.0f;
                            this.linear_attenuation    = 0.0f;
                            this.quadratic_attenuation = 0.0f;
                            this.falloff_angle         = 0.0f;
                            this.falloff_exponent      = 0.0f;
                        }

                        public Vector3 color;
                        public float   constant_attenuation;
                        public float   linear_attenuation;
                        public float   quadratic_attenuation;
                        public float   falloff_angle;
                        public float   falloff_exponent;
                    }
                    public class Point
                    {
                        public Vector3 color;
                        public float   constant_attenuation;
                        public float   linear_attenuation;
                        public float   quadratic_attenuation;

                        public Point()
                        {
                            this.color                 = Vector3.Zero;
                            this.constant_attenuation  = 0.0f;
                            this.linear_attenuation    = 0.0f;
                            this.quadratic_attenuation = 0.0f;
                        }
                    }
                }
            }
        }


        #endregion

        #region Library Materials

        public class LibraryMaterials
        {
            public List<Material> materials;

            public LibraryMaterials()
            {
                this.materials = new List<Material>();
            }

            public class Material
            {
                public string         id;
                public string         name;
                public InstanceEffect instance_effect;

                public Material()
                {
                    this.instance_effect = null;
                }

                public class InstanceEffect
                {
                    public string url;
                }
            }
        }
        
        #endregion

        #region Library Effects

        public class LibraryEffects
        {
            public List<Effect> effects;

            public LibraryEffects()
            {
                this.effects = new List<Effect>();
            }

            public class Effect
            {
                public string id;

                public ProfileCommon profile_common;

                public Effect()
                {
                    this.id             = string.Empty;

                    this.profile_common = null;
                }

                public class ProfileCommon
                {
                    public Technique      technique;

                    public List<NewParam> newparams;

                    public ProfileCommon()
                    {
                        this.technique = null;

                        this.newparams = new List<NewParam>();
                    }

                    public class NewParam
                    {
                        public string    elementType;
                        public string    sid;
                        public Surface   surface;
                        public Sampler2D sampler2D;

                        public NewParam()
                        {
                            this.elementType = string.Empty;
                            this.sid          = string.Empty;
                            this.surface      = null;
                            this.sampler2D    = null;
                        }

                        public class Surface
                        {
                            public string type;
                            public string init_from;
                            public string format;

                            public Surface()
                            {
                                this.type      = string.Empty;
                                this.init_from = string.Empty;
                                this.format    = string.Empty;
                            }
                        }

                        public class Sampler2D
                        {
                            public string source;
                            public string wrap_s;
                            public string wrap_t;
                            public string minfilter;
                            public string magfilter;
                            public string mipfilter;

                            public Sampler2D()
                            {
                                this.source    = string.Empty;
                                this.wrap_s    = string.Empty;
                                this.wrap_t    = string.Empty;
                                this.minfilter = string.Empty;
                                this.magfilter = string.Empty;
                                this.mipfilter = string.Empty;
                            }
                        }

                    }

                    public class Technique
                    {
                        public string   sid;
                        public string   elementType;
                        public Constant constant;
                        public Phong    phong;
                        public Blinn    blinn;
                        public Lambert  lambert;
                        
                        public Technique()
                        {
                            this.sid          = string.Empty;
                            this.elementType  = string.Empty;
                            this.constant     = null;
                            this.phong        = null;
                            this.blinn        = null;
                            this.lambert      = null;
                        }

                        public class Constant 
                        {
                            public common_color_or_texture_type  emission;
                            public common_color_or_texture_type  reflective;
                            public common_float_or_param_type    reflectivity;
                            public common_transparent_type       transparent;
                            public common_float_or_param_type    transparency;
                            public common_float_or_param_type    index_of_refraction;
                            
                            public Constant()
                            {
                                this.emission            = null;
                                this.reflective          = null;
                                this.reflectivity        = null;
                                this.transparency        = null;
                                this.transparent         = null;
                                this.index_of_refraction = null;
                            }
                        }
                        public class Phong    
                        {
                            public common_color_or_texture_type emission;
                            public common_color_or_texture_type ambient;
                            public common_color_or_texture_type diffuse;
                            public common_color_or_texture_type specular;
                            public common_float_or_param_type   shininess;
                            public common_color_or_texture_type reflective;
                            public common_float_or_param_type   reflectivity;
                            public common_transparent_type      transparent;
                            public common_float_or_param_type   transparency;
                            public common_float_or_param_type   index_of_refraction;
                            

                            public Phong()
                            {
                                this.ambient             = null;
                                this.diffuse             = null;
                                this.emission            = null;
                                this.reflective          = null;
                                this.reflectivity        = null;
                                this.shininess           = null;
                                this.specular            = null;
                                this.transparency        = null;
                                this.transparent         = null;
                                this.index_of_refraction = null;
                            }
                        }
                        public class Blinn    
                        {
                            public common_color_or_texture_type emission;
                            public common_color_or_texture_type ambient;
                            public common_color_or_texture_type diffuse;
                            public common_color_or_texture_type specular;
                            public common_float_or_param_type   shininess;
                            public common_color_or_texture_type reflective;
                            public common_float_or_param_type   reflectivity;
                            public common_transparent_type      transparent;
                            public common_float_or_param_type   transparency;
                            public common_float_or_param_type   index_of_refraction;
											
                            public Blinn()
                            {
                                this.ambient             = null;
                                this.diffuse             = null;
                                this.emission            = null;
                                this.reflective          = null;
                                this.reflectivity        = null;
                                this.shininess           = null;
                                this.specular            = null;
                                this.transparency        = null;
                                this.transparent         = null;
                                this.index_of_refraction = null;
                            }
                        }
                        public class Lambert  
                        {
                            public common_color_or_texture_type emission;
                            public common_color_or_texture_type ambient;
                            public common_color_or_texture_type diffuse;
                            public common_color_or_texture_type reflective;
                            public common_float_or_param_type   reflectivity;
                            public common_transparent_type      transparent;
                            public common_float_or_param_type   transparency;
                            public common_float_or_param_type   index_of_refraction;

                            public Lambert()
                            {
                                this.ambient             = null;
                                this.diffuse             = null;
                                this.emission            = null;
                                this.reflective          = null;
                                this.reflectivity        = null;
                                this.transparency        = null;
                                this.transparent         = null;
                                this.index_of_refraction = null;
                            }
                        }
                    }
                }
            }

        }
        
        #endregion

        #region Library Geometries

        public class LibraryGeometries
        {
            public List<Geometry> geometries;

            public LibraryGeometries()
            {
                this.geometries = new List<Geometry>();
            }

            public class Geometry
            {
                public string id;
                public string name;
                public Mesh   mesh;

                public Geometry()
                {
                    this.id   = string.Empty;
                    this.name = string.Empty;
                    this.mesh = null;
                }

                public class Mesh
                {
                    public List<Source>    sources;
                    public Vertices        vertices;
                    public Triangles       triangles;
                    public PolyList        polylist;
                    public Polygons        polygons;

                    public Mesh()
                    {
                        this.sources       = new List<Source>();
                        this.vertices      = null;
                        this.triangles     = null;
                        this.polylist      = null;
                        this.polygons      = null;
                    }

                    public class Source   
                    {
                        public string          id;
                        public FloatArray      float_array;
                        public TechniqueCommon technique_common;

                        public Source()
                        {
                            this.id               = string.Empty;
                            this.float_array      = null;
                            this.technique_common = null;
                        }

                        public class FloatArray
                        {
                            public string      id;
                            public int         count;
                            public float []    values;

                            public FloatArray()
                            {
                                this.id     = string.Empty;
                                this.count  = 0;
                                this.values = null;
                            }
                        }
                        
                        public class TechniqueCommon
                        {
                            public Accessor accessor;

                            public TechniqueCommon()
                            {
                                this.accessor = null;
                            }

                            public class Accessor
                            {
                                public string      source;
                                public int         count;
                                public int         stride;
                                public List<Param> _params;

                                public Accessor()
                                {
                                    this.source    = string.Empty;
                                    this.count     = 0;
                                    this.stride    = 0;
                                    this._params = new List<Param>();
                                }

                                public class Param
                                {
                                    public string name;
                                    public string type;

                                    public Param()
                                    {
                                        this.name = string.Empty;
                                        this.type = string.Empty;
                                    }
                                }
                            }
                        }
                    }

                    public class Vertices 
                    {
                        public string id;
                        public Input  input;

                        public Vertices()
                        {
                            this.id    = string.Empty;
                            this.input = null;
                        }

                        public class Input
                        {
                            public string semantic;
                            public string source;

                            public Input()
                            {
                                this.semantic = string.Empty;
                                this.source   = string.Empty;
                            }
                        }
                    }

                    public class PolyList 
                    {
                        public string       material;
                        public int          count;
                        public List<Input>  inputs;
                        public P            p;
                        public Vcount       vcount;

                        public PolyList()
                        {
                            this.material  = string.Empty;
                            this.count     = 0;
                            this.inputs    = new List<Input>();
                            this.p         = null;
                            this.vcount    = null;
                        }

                        public class Input
                        {
                            public string sematic;
                            public string source;
                            public int    offset;
                            public int    set;

                            public Input()
                            {
                                this.sematic = string.Empty;
                                this.source  = string.Empty;
                                this.offset  = 0;
                                this.set     = 0;
                            }
                        }
                        public class Vcount
                        {
                            public int[] values;

                            public Vcount()
                            {
                                values = null;
                            }
                        }
                        public class P
                        {
                            public int[] values;

                            public P()
                            {
                                values = null;
                            }
                        }
                    }

                    public class Triangles
                    {
                        public string      material;
                        public int         count;
                        public List<Input> inputs;
                        public P           p;
                        public Vcount      vcount;

                        public Triangles()
                        {
                            this.material  = string.Empty;
                            this.count     = 0;
                            this.inputs    = new List<Input>();
                            this.p         = null;
                            this.vcount    = null;
                        }

                        public class Input
                        {
                            public string sematic;
                            public string source;
                            public int    offset;
                            public int    set;

                            public Input()
                            {
                                this.sematic = string.Empty;
                                this.source  = string.Empty;
                                this.offset  = 0;
                                this.set     = 0;
                            }
                        }
                        public class Vcount
                        {
                            public int[] values;

                            public Vcount()
                            {
                                values = null;
                            }
                        }
                        public class P
                        {
                            public int [] values;

                            public P()
                            {
                                values = null;
                            }
                        }
                    }

                    public class Polygons 
                    {
                        public string       material;
                        public int          count;
                        public List<Input>  inputs;
                        public P            p;
                        public Vcount       vcount;

                        public Polygons()
                        {
                            this.material  = string.Empty;
                            this.count     = 0;
                            this.inputs    = new List<Input>();
                            this.p         = null;
                            this.vcount    = null;
                        }

                        public class Input
                        {
                            public string sematic;
                            public string source;
                            public int    offset;
                            public int    set;

                            public Input()
                            {
                                this.sematic = string.Empty;
                                this.source  = string.Empty;
                                this.offset  = 0;
                                this.set     = 0;
                            }
                        }
                        public class Vcount
                        {
                            public int[] values;

                            public Vcount()
                            {
                                values = null;
                            }
                        }
                        public class P
                        {
                            public int[] values;

                            public P()
                            {
                                values = null;
                            }
                        }
                    }
                }
            }
        }

        #endregion

        #region Library Controllers

        public class LibraryControllers
        {
            public List<Controller> controllers;

            public LibraryControllers()
            {
                this.controllers = new List<Controller>();
            }

            public class Controller
            {
                public string id;
                public Skin   skin;

                public Controller()
                {
                    this.id   = string.Empty;
                    this.skin = null;
                }

                public class Skin
                {
                    public string        source;
                    public Matrix        bind_shape_matrix;
                    public List<Source>  sourceList;
                    public Joints        joints;
                    public VertexWeights vertex_weights;

                    public Skin()
                    {
                        this.source            = string.Empty;
                        this.bind_shape_matrix = Matrix.Identity;
                        this.sourceList        = new List<Source>();
                        this.joints            = null;
                        this.vertex_weights    = null;
                    }

                    public class Source 
                    {
                        public string          id;
                        public string          elementType;
                        public NameArray       name_array;
                        public FloatArray      float_array;
                        public TechniqueCommon technique_common;

                        public Source()
                        {
                            this.id               = string.Empty;
                            this.name_array       = null;
                            this.float_array      = null;
                            this.technique_common = null;
                        }

                        public class NameArray
                        {
                            public string       id;
                            public int          count;
                            public List<string> values;

                            public NameArray()
                            {
                                this.id     = string.Empty;
                                this.count  = 0;
                                this.values = new List<string>();
                            }
                        }

                        public class FloatArray
                        {
                            public string      id;
                            public int         count;
                            public List<float> values;

                            public FloatArray()
                            {
                                this.id     = string.Empty;
                                this.count  = 0;
                                this.values = new List<float>();
                            }
                        }

                        public class TechniqueCommon
                        {
                            public Accessor accessor;

                            public TechniqueCommon()
                            {
                                this.accessor = null;
                            }

                            public class Accessor
                            {
                                public string source;
                                public int    count;
                                public int    stride;
                                public List<Param> param_list;

                                public Accessor()
                                {
                                    this.source     = string.Empty;
                                    this.count      = 0;
                                    this.stride     = 0;
                                    this.param_list = new List<Param>();
                                }

                                public class Param
                                {
                                    public string name;
                                    public string type;

                                    public Param()
                                    {
                                        this.name = string.Empty;
                                        this.type = string.Empty;
                                    }
                                }
                            }
                        }

                    }

                    public class Joints 
                    {
                        public List<Input> inputList;

                        public Joints()
                        {
                            this.inputList = new List<Input>();
                        }

                        public class Input
                        {
                            public string semantic;
                            public string source;

                            public Input()
                            {
                                this.semantic = string.Empty;
                                this.source   = string.Empty;
                            }
                        }
                    }

                    public class VertexWeights
                    {
                        public int         count;
                        public List<Input> inputList;
                        public List<int>   vcount;
                        public List<int>   v;

                        public VertexWeights()
                        {
                            this.count     = 0;
                            this.inputList = new List<Input>();
                            this.vcount    = new List<int>();
                            this.v         = new List<int>();
                        }

                        public class Input
                        {
                            public string    sematic;
                            public string    source;
                            public int       offset;
         
                            public Input()
                            {
                                this.sematic = string.Empty;
                                this.source  = string.Empty;
                                this.offset  = 0;
                            }
                        }
                    }
                }
            }
        }

        #endregion

        #region Library Visual Scenes

        public class LibraryVisualScenes
        {
            public VisualScene visual_scene;

            public LibraryVisualScenes()
            {
                this.visual_scene = null;
            }

            public class VisualScene
            {
                public string      id;
                public string      name;
                public List<Node>  nodes;
                
                public VisualScene()
                {
                    this.id     = string.Empty;
                    this.name   = string.Empty;
                    this.nodes  = new List<Node>();
                }
    
                public class Node
                {
                    public string           elementType;
                    public string           id;
                    public string           sid;
                    public string           name;
                    public string           type;
                    public Matrix           matrix;
                    public Vector3          translate;
                    public Vector4          rotate;
                    public Vector3          scale;
                    public List<Matrix>     matrices;

                    public InstanceGeometry instance_geometry;
                    public InstanceCamera   instance_camera;
                    public InstanceLight    instance_light;
                    public List<Node>       nodes;

                    public Node()
                    {
                        this.elementType       = string.Empty;
                        this.id                = string.Empty;
                        this.sid               = string.Empty;
                        this.name              = string.Empty;
                        this.type              = string.Empty;
                        this.matrix            = Matrix.Identity;
                        this.translate         = Vector3.Zero;
                        this.rotate            = Vector4.Zero;
                        this.scale             = Vector3.Zero;
                        this.instance_geometry = null;
                        this.instance_camera   = null;
                        this.instance_light    = null;
                        this.nodes             = new List<Node>();
                    }

                    public class InstanceLight
                    {
                        public string url;

                        public InstanceLight()
                        {
                            this.url = string.Empty;
                        }
                    }

                    public class InstanceCamera
                    {
                        public string url;

                        public InstanceCamera()
                        {
                            this.url = string.Empty;    
                        }
                    }

                    public class InstanceGeometry
                    {
                        public string       url;
                        public BindMaterial bind_material;

                        public InstanceGeometry()
                        {
                            this.url           = string.Empty;
                            this.bind_material = null;
                        }

                        public class BindMaterial
                        {
                            public TechniqueCommon technique_common;

                            public BindMaterial()
                            {
                                this.technique_common = null;
                            }

                            public class TechniqueCommon
                            {
                                public InstanceMaterial instance_material;

                                public TechniqueCommon()
                                {
                                    this.instance_material = null;
                                }

                                public class InstanceMaterial
                                {
                                    public string symbol;
                                    public string target;

                                    public InstanceMaterial()
                                    {
                                        this.symbol = string.Empty;

                                        this.target = string.Empty;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        #endregion

        #region Scene

        public class Scene
        {
            public InstanceVisualScene instance_visual_scene;

            public Scene()
            {
                this.instance_visual_scene = null;
            }

            public class InstanceVisualScene
            {
                public string url;

                public InstanceVisualScene()
                {
                    this.url = string.Empty;
                }
            }
        }

        #endregion
    }

    public partial class Document
    {
        #region Read Asset Section

        private static void read_asset_contributor(Document.Asset.Contributor contributor, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "author")
                {
                    contributor.author = e.Value;
                }
                if (e.Name.LocalName == "authoring_tool")
                {
                    contributor.authoring_tool = e.Value;
                }
                if (e.Name.LocalName == "comments")
                {
                    contributor.comments = e.Value;
                }
            }
        }
        private static void read_asset_unit(Document.Asset.Unit unit, XElement element)
        {
            foreach (XAttribute e in element.Attributes())
            {
                if (e.Name == "meter")
                {
                    float.TryParse(e.Value, out unit.meter);
                }
                if (e.Name == "name")
                {
                    unit.name = e.Value;
                }
            }
        }
        private static void read_asset(Document.Asset asset, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "contributor")
                {
                    Document.Asset.Contributor contributer = new Asset.Contributor();

                    read_asset_contributor(contributer, e);

                    asset.contributor = contributer;
                }
                if (e.Name.LocalName == "unit")
                {
                    Document.Asset.Unit unit = new Document.Asset.Unit();

                    read_asset_unit(unit, e);

                    asset.unit = unit;
                }
                if (e.Name.LocalName == "created")
                {
                    DateTime.TryParse(e.Value, out asset.created);
                }
                if (e.Name.LocalName == "modified")
                {
                    DateTime.TryParse(e.Value, out asset.modified);
                }
                if (e.Name.LocalName == "up_axis")
                {
                    asset.up_axis = e.Value;
                }
            }
        }
        
        #endregion

        #region Read Library Animations

        private static void read_library_animations_animation_source_float_array(Document.LibraryAnimations.Animation.Source.FloatArray float_array, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")    float_array.id = a.Value;

                if (a.Name == "count") int.TryParse(a.Value, out float_array.count);
            }

            element.Value = element.Value.Replace("\n", " ");

            string [] data = element.Value.Split(new char[] { ' ' });

            foreach (string d in data)
            {
                float v = 0.0f;

                float.TryParse(d, out v);
               
                float_array.values.Add(v);
            }

        }
        private static void read_library_animations_animation_source_name_array(Document.LibraryAnimations.Animation.Source.NameArray name_array, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")    name_array.id = a.Value;

                if (a.Name == "count") int.TryParse(a.Value, out name_array.count);
            }

            string[] data = element.Value.Split(new char[] { ' ' });

            foreach (string d in data)
            {
                name_array.values.Add(d);
            }
        }
        private static void read_library_animations_animation_source_technique_common_accessor_param(Document.LibraryAnimations.Animation.Source.TechniqueCommon.Accessor.Param param, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "name")
                {
                    param.name = a.Value;
                }

                if (a.Name == "type")
                {
                    param.type = a.Value;
                }
            }
        }
        private static void read_library_animations_animation_source_technique_common_accessor(Document.LibraryAnimations.Animation.Source.TechniqueCommon.Accessor accessor, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "source")
                {
                    accessor.source = a.Value;
                }

                if (a.Name == "count")
                {
                    int.TryParse(a.Value, out accessor.count);
                }

                if (a.Name == "stride")
                {
                    int.TryParse(a.Value, out accessor.stride);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "param")
                {
                    Document.LibraryAnimations.Animation.Source.TechniqueCommon.Accessor.Param param = new LibraryAnimations.Animation.Source.TechniqueCommon.Accessor.Param();

                    read_library_animations_animation_source_technique_common_accessor_param(param, e);

                    accessor.param_list.Add(param);
                }
            }
        }
        private static void read_library_animations_animation_source_technique_common(Document.LibraryAnimations.Animation.Source.TechniqueCommon technique_common, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "accessor")
                {
                    Document.LibraryAnimations.Animation.Source.TechniqueCommon.Accessor accessor = new LibraryAnimations.Animation.Source.TechniqueCommon.Accessor();

                    read_library_animations_animation_source_technique_common_accessor(accessor, e);

                    technique_common.accessor = accessor;
                }
            }
        }
        private static void read_library_animations_animation_source(Document.LibraryAnimations.Animation.Source source, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id") source.id = a.Value;
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "float_array")
                {
                    source.elementType = "float_array";

                    Document.LibraryAnimations.Animation.Source.FloatArray float_array = new LibraryAnimations.Animation.Source.FloatArray();

                    read_library_animations_animation_source_float_array(float_array, e);

                    source.float_array = float_array;
                }

                if (e.Name.LocalName.ToLower() == "name_array")
                {
                    source.elementType = "name_array";

                    Document.LibraryAnimations.Animation.Source.NameArray name_array = new LibraryAnimations.Animation.Source.NameArray();

                    read_library_animations_animation_source_name_array(name_array, e);

                    source.name_array = name_array;
                }

                if (e.Name.LocalName == "technique_common")
                {
                    Document.LibraryAnimations.Animation.Source.TechniqueCommon technique_common = new LibraryAnimations.Animation.Source.TechniqueCommon();

                    read_library_animations_animation_source_technique_common(technique_common, e);

                    source.technique_common = technique_common;
                }
            }
        }
        private static void read_library_animations_animation_sampler_input(Document.LibraryAnimations.Animation.Sampler.Input input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "semantic")
                {
                    input.semantic = a.Value;
                }
                if (a.Name == "source")
                {
                    input.source = a.Value.Replace("#", string.Empty);
                }
            }
        }
        private static void read_library_animations_animation_sampler(Document.LibraryAnimations.Animation.Sampler sampler, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    sampler.id = a.Value.Replace("#", string.Empty);
                }
            }
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "input")
                {
                    Document.LibraryAnimations.Animation.Sampler.Input input = new LibraryAnimations.Animation.Sampler.Input();

                    read_library_animations_animation_sampler_input(input, e);

                    sampler.inputs.Add(input);
                }
            }
        }
        private static void read_library_animations_animation_channel(Document.LibraryAnimations.Animation.Channel channel, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "source")
                {
                    channel.source = a.Value;
                }

                if (a.Name == "target")
                {
                    channel.target = a.Value;
                }
            }
        }
        private static void read_library_animations_animation(Document.LibraryAnimations.Animation animation, XElement element)
        {
            foreach(XAttribute a in element.Attributes())
            {
                if (a.Name == "id") animation.id = a.Value;
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "source")
                {
                    Document.LibraryAnimations.Animation.Source source = new LibraryAnimations.Animation.Source();

                    read_library_animations_animation_source(source, e);

                    animation.sources.Add(source);
                }
                if (e.Name.LocalName == "sampler")
                {
                    LibraryAnimations.Animation.Sampler sampler = new LibraryAnimations.Animation.Sampler();

                    read_library_animations_animation_sampler(sampler, e);

                    animation.sampler = sampler;
                }
                if (e.Name.LocalName == "channel")
                {
                    LibraryAnimations.Animation.Channel channel = new LibraryAnimations.Animation.Channel();

                    read_library_animations_animation_channel(channel, e);

                    animation.channel = channel;
                }
            }


        }
        private static void read_library_animations(Document.LibraryAnimations library_animations, XElement element)
        {
            foreach (XElement e in element.Elements())
            {   
                if(e.Name.LocalName == "animation") 
                {
                    Document.LibraryAnimations.Animation animation = new LibraryAnimations.Animation();
                    
                    read_library_animations_animation(animation, e);

                    library_animations.animations.Add(animation);
                }
                    
            }
        }

        #endregion

        #region Read Library Animation Clips
        private static void read_library_animation_clips_animation_clip_instance_animation(Document.LibraryAnimationClips.AnimationClip.InstanceAnimation instance_animation, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "url")
                {
                    instance_animation.url = a.Value.Replace("#", string.Empty);
                }
            }
        }
        private static void read_library_animation_clips_animation_clip(Document.LibraryAnimationClips.AnimationClip animation_clip, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    animation_clip.id = a.Value;
                }

                if (a.Name == "start")
                {
                    float.TryParse(a.Value, out animation_clip.start);
                }

                if (a.Name == "end")
                {
                    float.TryParse(a.Value, out animation_clip.end);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "instance_animation")
                {
                    Document.LibraryAnimationClips.AnimationClip.InstanceAnimation instance_animation = new LibraryAnimationClips.AnimationClip.InstanceAnimation();

                    read_library_animation_clips_animation_clip_instance_animation(instance_animation, e);

                    animation_clip.instance_animations.Add(instance_animation);
                }
            }
        }
        private static void read_library_animation_clips(Document.LibraryAnimationClips library_animation_clips, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "animation_clip")
                {
                    Document.LibraryAnimationClips.AnimationClip animationClip = new LibraryAnimationClips.AnimationClip();

                    read_library_animation_clips_animation_clip(animationClip, e);

                    library_animation_clips.animation_clipList.Add(animationClip);
                }
            }
        }
        #endregion

        #region Read Library Cameras
        private static void read_library_cameras_camera_optics_technique_common_perspective(Document.LibraryCameras.Camera.Optics.TechniqueCommon.Perspective perspective, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "xfov")
                {
                    float.TryParse(e.Value, out perspective.xfov);
                }
                if (e.Name.LocalName == "aspect_ratio")
                {
                    float.TryParse(e.Value, out perspective.aspect_ratio);
                }
                if (e.Name.LocalName == "znear")
                {
                    float.TryParse(e.Value, out perspective.znear);
                }
                if (e.Name.LocalName == "zfar")
                {
                    float.TryParse(e.Value, out perspective.zfar);
                }
            }
        }
        private static void read_library_cameras_camera_optics_technique_common(Document.LibraryCameras.Camera.Optics.TechniqueCommon technique_common, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "perspective")
                {
                    Document.LibraryCameras.Camera.Optics.TechniqueCommon.Perspective perspective = new LibraryCameras.Camera.Optics.TechniqueCommon.Perspective();

                    read_library_cameras_camera_optics_technique_common_perspective(perspective, e);

                    technique_common.perspective = perspective;
                }
            }
        }
        private static void read_library_cameras_camera_optics(Document.LibraryCameras.Camera.Optics optics, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "technique_common")
                {
                    Document.LibraryCameras.Camera.Optics.TechniqueCommon technique_common = new LibraryCameras.Camera.Optics.TechniqueCommon();

                    read_library_cameras_camera_optics_technique_common(technique_common, e);

                    optics.technique_common = technique_common;
                }
            }
        }
        private static void read_library_cameras_camera(Document.LibraryCameras.Camera camera, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    camera.id = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "optics")
                {
                    Document.LibraryCameras.Camera.Optics optics = new LibraryCameras.Camera.Optics();

                    read_library_cameras_camera_optics(optics, e);

                    camera.optics = optics;
                }
            }
        }
        private static void read_library_cameras(Document.LibraryCameras library_cameras, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if(e.Name.LocalName ==  "camera")  
                {
                    Document.LibraryCameras.Camera camera = new LibraryCameras.Camera();

                    read_library_cameras_camera(camera, e);

                    library_cameras.cameras.Add(camera);

                }
            }
        }
        #endregion

        #region Read Library Lights

        private static void read_library_lights_light_technique_common_spot(Document.LibraryLights.Light.TechniqueCommon.Spot spot, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "color")
                {
                    Vector3.TryParse(e.Value, out spot.color);
                }
                if (e.Name.LocalName == "constant_attenuation")
                {
                    float.TryParse(e.Value, out spot.constant_attenuation);
                }
                if (e.Name.LocalName == "linear_attenuation")
                {
                    float.TryParse(e.Value, out spot.linear_attenuation);
                }
                if (e.Name.LocalName == "quadratic_attenuation")
                {
                    float.TryParse(e.Value, out spot.quadratic_attenuation);
                }
                if (e.Name.LocalName == "falloff_angle")
                {
                    float.TryParse(e.Value, out spot.falloff_angle);
                }
                if (e.Name.LocalName == "falloff_exponent")
                {
                    float.TryParse(e.Value, out spot.falloff_exponent);
                }
            }
        }
        private static void read_library_lights_light_technique_common_point(Document.LibraryLights.Light.TechniqueCommon.Point point, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "color")
                {
                    Vector3.TryParse(e.Value, out point.color);
                }
                if (e.Name.LocalName == "constant_attenuation")
                {
                    float.TryParse(e.Value, out point.constant_attenuation);
                }
                if (e.Name.LocalName == "linear_attenuation")
                {
                    float.TryParse(e.Value, out point.linear_attenuation);
                }
                if (e.Name.LocalName == "quadratic_attenuation")
                {
                    float.TryParse(e.Value, out point.quadratic_attenuation);
                }
            }
        }
        private static void read_library_lights_light_technique_common_directional(Document.LibraryLights.Light.TechniqueCommon.Directional directional, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "color")
                {
                    Vector3.TryParse(e.Value, out directional.color);
                }
            }
        }
        private static void read_library_lights_light_technique_common(Document.LibraryLights.Light.TechniqueCommon technique_common, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "spot")
                {
                    technique_common.elementType = "spot";

                    Document.LibraryLights.Light.TechniqueCommon.Spot spot = new LibraryLights.Light.TechniqueCommon.Spot();

                    read_library_lights_light_technique_common_spot(spot, e);

                    technique_common.spot = spot;

                }
                if (e.Name.LocalName == "point")
                {
                    technique_common.elementType = "point";

                    Document.LibraryLights.Light.TechniqueCommon.Point point = new LibraryLights.Light.TechniqueCommon.Point();

                    read_library_lights_light_technique_common_point(point, e);

                    technique_common.point = point;
                }

                if (e.Name.LocalName == "directional")
                {
                    technique_common.elementType = "directional";

                    Document.LibraryLights.Light.TechniqueCommon.Directional directional = new LibraryLights.Light.TechniqueCommon.Directional();

                    read_library_lights_light_technique_common_directional(directional, e);

                    technique_common.directional = directional;
                }
            }
        }
        private static void read_library_lights_light(Document.LibraryLights.Light light, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    light.id = a.Value;
                }
            }
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "technique_common")
                {
                    Document.LibraryLights.Light.TechniqueCommon technique_common = new LibraryLights.Light.TechniqueCommon();

                    read_library_lights_light_technique_common(technique_common, e);

                    light.technique_common = technique_common;
                }
            }
        }
        private static void read_library_lights(Document.LibraryLights library_lights, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "light")
                {
                    Document.LibraryLights.Light light = new LibraryLights.Light();

                    read_library_lights_light(light, e);

                    library_lights.lights.Add(light);
                }
            }
        }

        #endregion

        #region Read Library Images
        private static void read_library_images_image(Document.LibraryImages.Image image, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    image.id = a.Value;
                }
                if (a.Name == "name")
                {
                    image.name = a.Value;
                }
            }
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "init_from")
                {
                    image.init_from = e.Value.Replace("file:///", string.Empty).Replace("%20", " ");
                }
            }
        }
        private static void read_library_images(Document.LibraryImages library_images, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "image")
                {
                    Document.LibraryImages.Image image = new Document.LibraryImages.Image();

                    read_library_images_image(image, e);

                    library_images.images.Add(image);
                }
            }
        }
        #endregion

        #region Read Library Materials

        private static void read_library_materials_material_instance_effect(Document.LibraryMaterials.Material.InstanceEffect instance_effect, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "url")
                {
                    instance_effect.url = a.Value.Replace("#", string.Empty);
                }
            }
        }
        private static void read_library_materials_material(Document.LibraryMaterials.Material material, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    material.id = a.Value;
                }
                if (a.Name == "name")
                {
                    material.name = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "instance_effect")
                {
                    Document.LibraryMaterials.Material.InstanceEffect instance_effect = new LibraryMaterials.Material.InstanceEffect();

                    read_library_materials_material_instance_effect(instance_effect, e);

                    material.instance_effect = instance_effect;
                }
            }
        }
        private static void read_library_materials(Document.LibraryMaterials library_materials, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "material")
                {
                    Document.LibraryMaterials.Material material = new Document.LibraryMaterials.Material();

                    read_library_materials_material(material, e);

                    library_materials.materials.Add(material);
                }
            }
        }

        #endregion

        #region Read Library Effects

        private static void read_common_float_or_param_type                                (common_float_or_param_type           input, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "float")
                {
                    float.TryParse(e.Value, out input.value);
                }
            }
        }
        private static void read_common_color_or_texture_type_texture                      (common_color_or_texture_type.Texture input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "texture")
                {
                    input.texture = element.Value;
                }

                if (a.Name == "texcoord")
                {
                    input.texcoord = element.Value;
                }
            }

        }
        private static void read_common_color_or_texture_type                              (common_color_or_texture_type         input, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "color")
                {
                    Vector4 v = new Vector4();

                    Vector4.TryParse(e.Value, out v);

                    input.color = new float4();

                    input.color.value = v;
                }

                if (e.Name.LocalName == "texture")
                {
                    common_color_or_texture_type.Texture texture = new common_color_or_texture_type.Texture();

                    read_common_color_or_texture_type_texture(texture, e);

                    input.texture = texture;
                }
            }
        }
        private static void read_common_transparent_type                                   (common_transparent_type              input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "opaque")
                {
                    switch(a.Value)
                    {
                        case "A_ONE"    : input.opaque = fx_opaque_enum.A_ONE;    break;

                        case "RGB_ZERO" : input.opaque = fx_opaque_enum.RGB_ZERO; break;

                        default: break;
                    }
                }

                foreach (XElement e in element.Elements())
                {
                    if (e.Name.LocalName == "color")
                    {
                        Vector4 v = new Vector4();

                        Vector4.TryParse(e.Value, out v);

                        input.color = new float4();

                        input.color.value = v;
                    }

                    if (e.Name.LocalName == "texture")
                    {
                        common_color_or_texture_type.Texture texture = new common_color_or_texture_type.Texture();

                        read_common_color_or_texture_type_texture(texture, e);

                        input.texture = texture;
                    }
                }
            }
        }
        private static void read_library_effects_effect_profile_common_technique_constant  (Document.LibraryEffects.Effect.ProfileCommon.Technique.Constant constant,  XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "emission")
                {
                    common_color_or_texture_type emission = new common_color_or_texture_type();

                    read_common_color_or_texture_type(emission, e);

                    constant.emission = emission;
                }

                if (e.Name.LocalName == "reflective")
                {
                    common_color_or_texture_type reflective = new common_color_or_texture_type();

                    read_common_color_or_texture_type(reflective, e);

                    constant.reflective = reflective;
                }

                if (e.Name.LocalName == "reflectivity")
                {
                    common_float_or_param_type reflectivity = new common_float_or_param_type();

                    read_common_float_or_param_type(reflectivity, e);

                    constant.reflectivity = reflectivity;
                }

                if (e.Name.LocalName == "transparent")
                {
                    common_transparent_type transparent = new common_transparent_type();

                    read_common_transparent_type(transparent, e);

                    constant.transparent = transparent;
                }

                if (e.Name.LocalName == "transparency")
                {
                    common_float_or_param_type transparency = new common_float_or_param_type();

                    read_common_float_or_param_type(transparency, e);

                    constant.transparency = transparency;
                }

                if (e.Name.LocalName == "index_of_refraction")
                {
                    common_float_or_param_type index_of_refraction = new common_float_or_param_type();

                    read_common_float_or_param_type(index_of_refraction, e);

                    constant.index_of_refraction = index_of_refraction;
                }
            }            
        }
        private static void read_library_effects_effect_profile_common_technique_phong     (Document.LibraryEffects.Effect.ProfileCommon.Technique.Phong    phong,     XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "emission")
                {
                    common_color_or_texture_type emission = new common_color_or_texture_type();

                    read_common_color_or_texture_type(emission, e);

                    phong.emission = emission;
                }

                if (e.Name.LocalName == "ambient")
                {
                    common_color_or_texture_type ambient = new common_color_or_texture_type();

                    read_common_color_or_texture_type(ambient, e);

                    phong.ambient = ambient;
                }

                if (e.Name.LocalName == "diffuse")
                {
                    common_color_or_texture_type diffuse = new common_color_or_texture_type();

                    read_common_color_or_texture_type(diffuse, e);

                    phong.diffuse = diffuse;
                }

                if (e.Name.LocalName == "specular")
                {
                    common_color_or_texture_type specular = new common_color_or_texture_type();

                    read_common_color_or_texture_type(specular, e);

                    phong.specular = specular;
                }

                if (e.Name.LocalName == "shininess")
                {
                    common_float_or_param_type shininess = new common_float_or_param_type();

                    read_common_float_or_param_type(shininess, e);

                    phong.shininess = shininess;
                }

                if (e.Name.LocalName == "reflective")
                {
                    common_color_or_texture_type reflective = new common_color_or_texture_type();

                    read_common_color_or_texture_type(reflective, e);

                    phong.reflective = reflective;
                }

                if (e.Name.LocalName == "reflectivity")
                {
                    common_float_or_param_type reflectivity = new common_float_or_param_type();

                    read_common_float_or_param_type(reflectivity, e);

                    phong.reflectivity = reflectivity;
                }

                if (e.Name.LocalName == "transparent")
                {
                    common_transparent_type transparent = new common_transparent_type();

                    read_common_transparent_type(transparent, e);

                    phong.transparent = transparent;
                }

                if (e.Name.LocalName == "transparency")
                {
                    common_float_or_param_type transparency = new common_float_or_param_type();

                    read_common_float_or_param_type(transparency, e);

                    phong.transparency = transparency;
                }

                if (e.Name.LocalName == "index_of_refraction")
                {
                    common_float_or_param_type index_of_refraction = new common_float_or_param_type();

                    read_common_float_or_param_type(index_of_refraction, e);

                    phong.index_of_refraction = index_of_refraction;
                }
            }
        }
        private static void read_library_effects_effect_profile_common_technique_blinn     (Document.LibraryEffects.Effect.ProfileCommon.Technique.Blinn    blinn,     XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "emission")
                {
                    common_color_or_texture_type emission = new common_color_or_texture_type();

                    read_common_color_or_texture_type(emission, e);

                    blinn.emission = emission;
                }

                if (e.Name.LocalName == "ambient")
                {
                    common_color_or_texture_type ambient = new common_color_or_texture_type();

                    read_common_color_or_texture_type(ambient, e);

                    blinn.ambient = ambient;
                }

                if (e.Name.LocalName == "diffuse")
                {
                    common_color_or_texture_type diffuse = new common_color_or_texture_type();

                    read_common_color_or_texture_type(diffuse, e);

                    blinn.diffuse = diffuse;
                }

                if (e.Name.LocalName == "specular")
                {
                    common_color_or_texture_type specular = new common_color_or_texture_type();

                    read_common_color_or_texture_type(specular, e);

                    blinn.specular = specular;
                }

                if (e.Name.LocalName == "shininess")
                {
                    common_float_or_param_type shininess = new common_float_or_param_type();

                    read_common_float_or_param_type(shininess, e);

                    blinn.shininess = shininess;
                }

                if (e.Name.LocalName == "reflective")
                {
                    common_color_or_texture_type reflective = new common_color_or_texture_type();

                    read_common_color_or_texture_type(reflective, e);

                    blinn.reflective = reflective;
                }

                if (e.Name.LocalName == "reflectivity")
                {
                    common_float_or_param_type reflectivity = new common_float_or_param_type();

                    read_common_float_or_param_type(reflectivity, e);

                    blinn.reflectivity = reflectivity;
                }

                if (e.Name.LocalName == "transparent")
                {
                    common_transparent_type transparent = new common_transparent_type();

                    read_common_transparent_type(transparent, e);

                    blinn.transparent = transparent;
                }

                if (e.Name.LocalName == "transparency")
                {
                    common_float_or_param_type transparency = new common_float_or_param_type();

                    read_common_float_or_param_type(transparency, e);

                    blinn.transparency = transparency;
                }
                if (e.Name.LocalName == "index_of_refraction")
                {
                    common_float_or_param_type index_of_refraction = new common_float_or_param_type();

                    read_common_float_or_param_type(index_of_refraction, e);

                    blinn.index_of_refraction = index_of_refraction;
                }
            }
        }
        private static void read_library_effects_effect_profile_common_technique_lambert   (Document.LibraryEffects.Effect.ProfileCommon.Technique.Lambert  lambert,   XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "emission")
                {
                    common_color_or_texture_type emission = new common_color_or_texture_type();

                    read_common_color_or_texture_type(emission, e);

                    lambert.emission = emission;
                }

                if (e.Name.LocalName == "ambient")
                {
                    common_color_or_texture_type ambient = new common_color_or_texture_type();

                    read_common_color_or_texture_type(ambient, e);

                    lambert.ambient = ambient;
                }

                if (e.Name.LocalName == "diffuse")
                {
                    common_color_or_texture_type diffuse = new common_color_or_texture_type();

                    read_common_color_or_texture_type(diffuse, e);

                    lambert.diffuse = diffuse;
                }

                if (e.Name.LocalName == "reflective")
                {
                    common_color_or_texture_type reflective = new common_color_or_texture_type();

                    read_common_color_or_texture_type(reflective, e);

                    lambert.reflective = reflective;
                }

                if (e.Name.LocalName == "reflectivity")
                {
                    common_float_or_param_type reflectivity = new common_float_or_param_type();

                    read_common_float_or_param_type(reflectivity, e);

                    lambert.reflectivity = reflectivity;
                }

                if (e.Name.LocalName == "transparent")
                {
                    common_transparent_type transparent = new common_transparent_type();

                    read_common_transparent_type(transparent, e);

                    lambert.transparent = transparent;
                }

                if (e.Name.LocalName == "transparency")
                {
                    common_float_or_param_type transparency = new common_float_or_param_type();

                    read_common_float_or_param_type(transparency, e);

                    lambert.transparency = transparency;
                }
                if (e.Name.LocalName == "index_of_refraction")
                {
                    common_float_or_param_type index_of_refraction = new common_float_or_param_type();

                    read_common_float_or_param_type(index_of_refraction, e);

                    lambert.index_of_refraction = index_of_refraction;
                }
            }
        }
        private static void read_library_effects_effect_profile_common_technique           (Document.LibraryEffects.Effect.ProfileCommon.Technique technique,          XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "sid")
                {
                    technique.sid = a.Value;
                }
            }
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "phong")
                {
                    technique.elementType = "phong";

                    Document.LibraryEffects.Effect.ProfileCommon.Technique.Phong phong = new LibraryEffects.Effect.ProfileCommon.Technique.Phong();

                    read_library_effects_effect_profile_common_technique_phong(phong, e);

                    technique.phong = phong;
                }

                if (e.Name.LocalName == "blinn")
                {
                    technique.elementType = "blinn";

                    Document.LibraryEffects.Effect.ProfileCommon.Technique.Blinn blinn = new LibraryEffects.Effect.ProfileCommon.Technique.Blinn();

                    read_library_effects_effect_profile_common_technique_blinn(blinn, e);

                    technique.blinn = blinn;
                }  
            }
        }
        private static void read_library_effects_effect_profile_common_newparam_surface    (Document.LibraryEffects.Effect.ProfileCommon.NewParam.Surface surface,     XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "type")
                {
                    surface.type = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "init_from")
                {
                    surface.init_from = e.Value;
                }

                if (e.Name.LocalName == "format")
                {
                    surface.format = e.Value;
                }
            }
        }
        private static void read_library_effects_effect_profile_common_newparam_sampler2D  (Document.LibraryEffects.Effect.ProfileCommon.NewParam.Sampler2D sampler2D, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "source")
                {
                    sampler2D.source = e.Value;
                }
                if (e.Name.LocalName == "wrap_s")
                {
                    sampler2D.wrap_s = e.Value;
                }
                if (e.Name.LocalName == "wrap_t")
                {
                    sampler2D.wrap_t = e.Value;
                }
                if (e.Name.LocalName == "minfilter")
                {
                    sampler2D.minfilter = e.Value;
                }
                if (e.Name.LocalName == "magfilter")
                {
                    sampler2D.magfilter = e.Value;
                }
                if (e.Name.LocalName == "mipfilter")
                {
                    sampler2D.mipfilter = e.Value;
                }
            }
        }
        private static void read_library_effects_effect_profile_common_newparam            (Document.LibraryEffects.Effect.ProfileCommon.NewParam newparam,            XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "sid")
                {
                    newparam.sid = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "surface")
                {
                    newparam.elementType = "surface";

                    Document.LibraryEffects.Effect.ProfileCommon.NewParam.Surface surface = new LibraryEffects.Effect.ProfileCommon.NewParam.Surface();

                    read_library_effects_effect_profile_common_newparam_surface(surface, e);

                    newparam.surface = surface;
                }

                if (e.Name.LocalName == "sampler2D")
                {
                    newparam.elementType = "sampler2D";

                    Document.LibraryEffects.Effect.ProfileCommon.NewParam.Sampler2D sampler2D = new LibraryEffects.Effect.ProfileCommon.NewParam.Sampler2D();

                    read_library_effects_effect_profile_common_newparam_sampler2D(sampler2D, e);

                    newparam.sampler2D = sampler2D;
                }
            }
        }
        private static void read_library_effects_effect_profile_common                     (Document.LibraryEffects.Effect.ProfileCommon profile_common,               XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "technique")
                {
                    Document.LibraryEffects.Effect.ProfileCommon.Technique technique = new LibraryEffects.Effect.ProfileCommon.Technique();

                    read_library_effects_effect_profile_common_technique(technique, e);

                    profile_common.technique = technique;
                }

                if (e.Name.LocalName == "newparam") 
                {
                    Document.LibraryEffects.Effect.ProfileCommon.NewParam newparam = new LibraryEffects.Effect.ProfileCommon.NewParam();

                    read_library_effects_effect_profile_common_newparam(newparam, e);

                    profile_common.newparams.Add(newparam);
                        
                }
            }
        }
        private static void read_library_effects_effect                                    (Document.LibraryEffects.Effect effect,          XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    effect.id = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName.ToLower() == "profile_common")
                {
                    Document.LibraryEffects.Effect.ProfileCommon profile_common = new LibraryEffects.Effect.ProfileCommon();

                    read_library_effects_effect_profile_common(profile_common, e);

                    effect.profile_common = profile_common;
                }
            }
        }
        private static void read_library_effects                                           (Document.LibraryEffects        library_effects, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "effect")
                {
                    Document.LibraryEffects.Effect effect = new Document.LibraryEffects.Effect();

                    read_library_effects_effect(effect, e);

                    library_effects.effects.Add(effect);
                }
            }
        }
        
        #endregion

        #region Read Library Geometries

        private static void read_library_geometries_geometry_mesh_source_float_array(Document.LibraryGeometries.Geometry.Mesh.Source.FloatArray float_array, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    float_array.id = a.Value;
                }

                if (a.Name == "count")
                {
                    int.TryParse(a.Value, out float_array.count);
                }
            }

            element.Value = element.Value.Replace("\n", " ").Trim();

            string [] s_data = element.Value.Split(new char[] {' '});

            float_array.values = new float[s_data.Length];

            for (int i = 0; i < s_data.Length; i++)
            {
                float v = 0.0f;

                if (float.TryParse(s_data[i], out v))
                {
                    float_array.values[i] = v;
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_float_array_technique_common_accessor_param(Document.LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon.Accessor.Param param, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "name")
                {
                    param.name = a.Value;
                }

                if (a.Name == "type")
                {
                    param.type = a.Value;
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_float_array_technique_common_accessor(Document.LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon.Accessor accessor, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "source")
                {
                    accessor.source = a.Value.Replace("#", string.Empty);
                }

                if (a.Name == "count")
                {
                    int.TryParse(a.Value, out accessor.count);
                }

                if (a.Name == "stride")
                {
                    int.TryParse(a.Value, out accessor.stride);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "param")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon.Accessor.Param param = new Document.LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon.Accessor.Param();

                    read_library_geometries_geometry_mesh_source_float_array_technique_common_accessor_param(param, e);
                    
                    accessor._params.Add(param);
                }
            }  
        }
        private static void read_library_geometries_geometry_mesh_source_float_array_technique_common(Document.LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon technique_common, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "accessor")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon.Accessor accessor = new LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon.Accessor();

                    read_library_geometries_geometry_mesh_source_float_array_technique_common_accessor(accessor, e);

                    technique_common.accessor = accessor;
                }
            }

        }
        private static void read_library_geometries_geometry_mesh_source(Document.LibraryGeometries.Geometry.Mesh.Source source, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    source.id = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "float_array")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Source.FloatArray float_array = new LibraryGeometries.Geometry.Mesh.Source.FloatArray();

                    read_library_geometries_geometry_mesh_source_float_array(float_array, e);

                    source.float_array = float_array;
                }

                if (e.Name.LocalName == "technique_common")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon technique_common = new LibraryGeometries.Geometry.Mesh.Source.TechniqueCommon();

                    read_library_geometries_geometry_mesh_source_float_array_technique_common(technique_common, e);

                    source.technique_common = technique_common;
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_vertices_input(Document.LibraryGeometries.Geometry.Mesh.Vertices.Input input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "semantic")
                {
                    input.semantic = a.Value;
                }

                if (a.Name == "source")
                {
                    input.source = a.Value.Replace("#", string.Empty);
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_vertices(Document.LibraryGeometries.Geometry.Mesh.Vertices vertices, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id") vertices.id = a.Value;
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "input")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Vertices.Input input = new LibraryGeometries.Geometry.Mesh.Vertices.Input();

                    read_library_geometries_geometry_mesh_source_vertices_input(input, e);

                    vertices.input = input;
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_triangles_input(Document.LibraryGeometries.Geometry.Mesh.Triangles.Input input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "semantic")
                {
                    input.sematic = a.Value;
                }
                if (a.Name == "source")
                {
                    input.source = a.Value.Replace("#", string.Empty);
                }

                if (a.Name == "offset")
                {
                    int.TryParse(a.Value, out input.offset);
                }

                if (a.Name == "set")
                {
                    int.TryParse(a.Value, out input.set);
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_triangles(Document.LibraryGeometries.Geometry.Mesh.Triangles triangles, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name.LocalName == "material")
                {
                    triangles.material = a.Value;
                }
                if (a.Name.LocalName == "count")
                {
                    int.TryParse(a.Value, out triangles.count);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "input")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Triangles.Input input = new Document.LibraryGeometries.Geometry.Mesh.Triangles.Input();

                    read_library_geometries_geometry_mesh_source_triangles_input(input, e);

                    triangles.inputs.Add(input);
                }

                if (e.Name.LocalName == "vcount")
                {
                    triangles.vcount = new LibraryGeometries.Geometry.Mesh.Triangles.Vcount();

                    e.Value = e.Value.Replace("\n", " ").Trim();

                    string[] data = e.Value.Split(new char[] { ' ' });

                    triangles.vcount.values = new int[data.Length];

                    for (int i = 0; i < data.Length; i++)
                    {
                        int idx = 0;

                        if (int.TryParse(data[i], out idx))
                        {
                            triangles.vcount.values[i] = idx;
                        }
                    }                    
                }

                if (e.Name.LocalName == "p") // Index Data
                {
                    triangles.p = new LibraryGeometries.Geometry.Mesh.Triangles.P();

                    e.Value = e.Value.Replace("\n", " ").Trim();

                    string[] data      = e.Value.Split(new char[] { ' ' });

                    triangles.p.values = new int[data.Length];

                    for (int i = 0; i < data.Length; i++)
                    {
                        int idx = 0;

                        if (int.TryParse(data[i], out idx))
                        {
                            triangles.p.values[i] = idx;
                        }
                    }
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_polylist_input(Document.LibraryGeometries.Geometry.Mesh.PolyList.Input input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "semantic")
                {
                    input.sematic = a.Value;
                }

                if (a.Name == "source")
                {
                    input.source = a.Value.Replace("#", string.Empty);
                }

                if (a.Name == "offset")
                {
                    int.TryParse(a.Value, out input.offset);
                }

                if (a.Name == "set")
                {
                    int.TryParse(a.Value, out input.set);
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_polylist(Document.LibraryGeometries.Geometry.Mesh.PolyList polylist, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name.LocalName == "material")
                {
                    polylist.material = a.Value;
                }

                if (a.Name.LocalName == "count")
                {
                    int.TryParse(a.Value, out polylist.count);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "input")
                {
                    Document.LibraryGeometries.Geometry.Mesh.PolyList.Input input = new Document.LibraryGeometries.Geometry.Mesh.PolyList.Input();

                    read_library_geometries_geometry_mesh_source_polylist_input(input, e);

                    polylist.inputs.Add(input);
                }


                if (e.Name.LocalName == "vcount")
                {
                    polylist.vcount = new LibraryGeometries.Geometry.Mesh.PolyList.Vcount();

                    e.Value = e.Value.Replace("\n", " ").Trim();

                    string[] data = e.Value.Split(new char[] { ' ' });

                    polylist.vcount.values = new int[data.Length];

                    for (int i = 0; i < data.Length; i++)
                    {
                        int idx = 0;

                        if (int.TryParse(data[i], out idx))
                        {
                            polylist.vcount.values[i] = idx;
                        }
                    }
                }

                if (e.Name.LocalName == "p") // Index Data
                {
                    polylist.p = new LibraryGeometries.Geometry.Mesh.PolyList.P();

                    e.Value = e.Value.Replace("\n", " ").Trim();

                    string[] data = e.Value.Split(new char[] { ' ' });

                    polylist.p.values = new int[data.Length];

                    for (int i = 0; i < data.Length; i++)
                    {
                        int idx = 0;

                        if (int.TryParse(data[i], out idx))
                        {
                            polylist.p.values[i] = idx;
                        }
                    }
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_polygons_input(Document.LibraryGeometries.Geometry.Mesh.Polygons.Input input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "semantic")
                {
                    input.sematic = a.Value;
                }

                if (a.Name == "source")
                {
                    input.source = a.Value.Replace("#", string.Empty);
                }

                if (a.Name == "offset")
                {
                    int.TryParse(a.Value, out input.offset);
                }

                if (a.Name == "set")
                {
                    int.TryParse(a.Value, out input.set);
                }
            }
        }
        private static void read_library_geometries_geometry_mesh_source_polygons(Document.LibraryGeometries.Geometry.Mesh.Polygons polygons, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name.LocalName == "material")
                {
                    polygons.material = a.Value;
                }

                if (a.Name.LocalName == "count")
                {
                    int.TryParse(a.Value, out polygons.count);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "input")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Polygons.Input input = new Document.LibraryGeometries.Geometry.Mesh.Polygons.Input();

                    read_library_geometries_geometry_mesh_source_polygons_input(input, e);

                    polygons.inputs.Add(input);
                }

                if (e.Name.LocalName == "vcount")
                {
                    polygons.vcount = new LibraryGeometries.Geometry.Mesh.Polygons.Vcount();

                    e.Value = e.Value.Replace("\n", " ").Trim();

                    string[] data = e.Value.Split(new char[] { ' ' });

                    polygons.vcount.values = new int[data.Length];

                    for (int i = 0; i < data.Length; i++)
                    {
                        int idx = 0;

                        if (int.TryParse(data[i], out idx))
                        {
                            polygons.vcount.values[i] = idx;
                        }
                    }
                }

                if (e.Name.LocalName == "p") // Index Data
                {
                    polygons.p = new LibraryGeometries.Geometry.Mesh.Polygons.P();

                    e.Value = e.Value.Replace("\n", " ").Trim();

                    string[] data = e.Value.Split(new char[] { ' ' });

                    polygons.p.values = new int[data.Length];

                    for (int i = 0; i < data.Length; i++)
                    {
                        int idx = 0;

                        if (int.TryParse(data[i], out idx))
                        {
                            polygons.p.values[i] = idx;
                        }
                    }
                }
            }
        }
        private static void read_library_geometries_geometry_mesh(Document.LibraryGeometries.Geometry.Mesh mesh, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "source")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Source source = new Document.LibraryGeometries.Geometry.Mesh.Source();
                    
                    read_library_geometries_geometry_mesh_source(source, e);

                    mesh.sources.Add(source);
                }

                if (e.Name.LocalName == "vertices")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Vertices vertices = new LibraryGeometries.Geometry.Mesh.Vertices();
                    
                    read_library_geometries_geometry_mesh_source_vertices(vertices, e);

                    mesh.vertices = vertices;
                }

                if (e.Name.LocalName == "triangles")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Triangles triangles = new Document.LibraryGeometries.Geometry.Mesh.Triangles();

                    read_library_geometries_geometry_mesh_source_triangles(triangles, e);
                    
                    mesh.triangles = triangles;
                }

                if (e.Name.LocalName == "polylist")
                {
                    Document.LibraryGeometries.Geometry.Mesh.PolyList polylist = new Document.LibraryGeometries.Geometry.Mesh.PolyList();

                    read_library_geometries_geometry_mesh_source_polylist(polylist, e);

                    mesh.polylist = polylist;
                }

                if (e.Name.LocalName == "polygons")
                {
                    Document.LibraryGeometries.Geometry.Mesh.Polygons polygons = new Document.LibraryGeometries.Geometry.Mesh.Polygons();

                    read_library_geometries_geometry_mesh_source_polygons(polygons, e);

                    mesh.polygons = polygons;
                }
            }
        }

        private static void read_library_geometries_geometry(Document.LibraryGeometries.Geometry geometry, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    geometry.id = a.Value;
                }

                if (a.Name == "name")
                {
                    geometry.name = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "mesh")
                {
                    Document.LibraryGeometries.Geometry.Mesh mesh = new LibraryGeometries.Geometry.Mesh();

                    read_library_geometries_geometry_mesh(mesh, e);

                    geometry.mesh = mesh;
                }
            }
        }

        private static void read_library_geometries(Document.LibraryGeometries library_geometries, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "geometry")
                {
                    Document.LibraryGeometries.Geometry geometry = new Document.LibraryGeometries.Geometry();

                    read_library_geometries_geometry(geometry, e);

                    library_geometries.geometries.Add(geometry);
                }
            }  
        }

        #endregion

        #region Read Library Controllers

        private static void read_library_controllers_controller_skin_source_technique_common_accessor_param(Document.LibraryControllers.Controller.Skin.Source.TechniqueCommon.Accessor.Param param, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "name")
                {
                    param.name = a.Value;
                }

                if (a.Name == "type")
                {
                    param.type = a.Value;
                }
            }
        }
        private static void read_library_controllers_controller_skin_source_technique_common_accessor(Document.LibraryControllers.Controller.Skin.Source.TechniqueCommon.Accessor accessor, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "source")
                {
                    accessor.source = a.Value.Replace("#", string.Empty);
                }

                if (a.Name == "count")
                {
                    int.TryParse(a.Value, out accessor.count);
                }

                if (a.Name == "stride")
                {
                    int.TryParse(a.Value, out accessor.stride);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "param")
                {
                    Document.LibraryControllers.Controller.Skin.Source.TechniqueCommon.Accessor.Param param = new LibraryControllers.Controller.Skin.Source.TechniqueCommon.Accessor.Param();

                    read_library_controllers_controller_skin_source_technique_common_accessor_param(param, e);

                    accessor.param_list.Add(param);
                }
            }
        }
        private static void read_library_controllers_controller_skin_source_technique_common(Document.LibraryControllers.Controller.Skin.Source.TechniqueCommon technique_common, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "accessor")
                {
                    Document.LibraryControllers.Controller.Skin.Source.TechniqueCommon.Accessor accessor = new LibraryControllers.Controller.Skin.Source.TechniqueCommon.Accessor();

                    read_library_controllers_controller_skin_source_technique_common_accessor(accessor, e);

                    technique_common.accessor = accessor;
                }
            }
        }
        private static void read_library_controllers_controller_skin_source_float_array(Document.LibraryControllers.Controller.Skin.Source.FloatArray float_array, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    float_array.id = a.Value;  
                }

                if (a.Name == "count")
                {
                    int.TryParse(a.Value, out float_array.count);
                }
            }

            element.Value = element.Value.Replace("\n", " ");

            string[] data = element.Value.Split(new char[] { ' ' });

            foreach (string d in data)
            {
                float i = 0.0f;

                float.TryParse(d, out i);
                
                float_array.values.Add(i);
                
            }
         
        }
        private static void read_library_controllers_controller_skin_source_name_array(Document.LibraryControllers.Controller.Skin.Source.NameArray name_array, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    name_array.id = a.Value;
                }

                if (a.Name == "count")
                {
                    int.TryParse(a.Value, out name_array.count);
                }
            }

        
            string[] data = element.Value.Split(new char[] { ' ' });
             
            foreach (string d in data)
            {
                name_array.values.Add(d);   
            }
             
        }
        private static void read_library_controllers_controller_skin_source(Document.LibraryControllers.Controller.Skin.Source source, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    source.id = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "float_array")
                {
                    source.elementType = "float_array";

                    Document.LibraryControllers.Controller.Skin.Source.FloatArray float_array = new LibraryControllers.Controller.Skin.Source.FloatArray();

                    read_library_controllers_controller_skin_source_float_array(float_array, e);

                    source.float_array = float_array;
                }

                if (e.Name.LocalName.ToLower() == "name_array")
                {
                    source.elementType = "name_array";

                    Document.LibraryControllers.Controller.Skin.Source.NameArray name_array = new LibraryControllers.Controller.Skin.Source.NameArray();

                    read_library_controllers_controller_skin_source_name_array(name_array, e);

                    source.name_array = name_array;
                }

                if (e.Name.LocalName == "technique_common")
                {
                    Document.LibraryControllers.Controller.Skin.Source.TechniqueCommon technique_common = new LibraryControllers.Controller.Skin.Source.TechniqueCommon();

                    read_library_controllers_controller_skin_source_technique_common(technique_common, e);

                    source.technique_common = technique_common;
                }
            }
        }
        private static void read_library_controllers_controller_skin_joints_input(Document.LibraryControllers.Controller.Skin.Joints.Input input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "semantic")
                {
                    input.semantic = a.Value;
                }

                if (a.Name == "source")
                {
                    input.source = a.Value.Replace("#", string.Empty);
                }
            }
        }
        private static void read_library_controllers_controller_skin_joints(Document.LibraryControllers.Controller.Skin.Joints joints, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if(e.Name.LocalName == "input") 
                {
                    Document.LibraryControllers.Controller.Skin.Joints.Input input = new LibraryControllers.Controller.Skin.Joints.Input();

                    read_library_controllers_controller_skin_joints_input(input, e);

                    joints.inputList.Add(input);
                }
            }
        }
        private static void read_library_controllers_controller_skin_vertex_weights_input(Document.LibraryControllers.Controller.Skin.VertexWeights.Input input, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "semantic")
                {
                    input.sematic = a.Value;
                }

                if (a.Name == "source")
                {
                    input.source = a.Value.Replace("#", string.Empty);
                }

                if (a.Name == "offset")
                {
                    int.TryParse(a.Value, out input.offset);
                }
            }
        }
        private static void read_library_controllers_controller_skin_vertex_weights(Document.LibraryControllers.Controller.Skin.VertexWeights vertex_weights, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "count")
                {
                    int.TryParse(a.Value, out vertex_weights.count);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if(e.Name.LocalName == "input") 
                {
                    Document.LibraryControllers.Controller.Skin.VertexWeights.Input input = new LibraryControllers.Controller.Skin.VertexWeights.Input();

                    read_library_controllers_controller_skin_vertex_weights_input(input, e);

                    vertex_weights.inputList.Add(input);
                }

                if (e.Name.LocalName == "vcount")
                {
                    e.Value = e.Value.Replace("\n", " ");

                    string[] data = e.Value.Split(new char[] { ' ' });

                    foreach (string d in data)
                    {
                        int i = 0;

                        int.TryParse(d, out i);

                        vertex_weights.vcount.Add(i);
                    }
                }

                if (e.Name.LocalName == "v")
                {
                    e.Value = e.Value.Replace("\n", " ");

                    string[] data = e.Value.Split(new char[] { ' ' });

                    foreach (string d in data)
                    {
                        int i = 0;

                        int.TryParse(d, out i);

                        vertex_weights.v.Add(i);
                    }
                }
            }
        }
        private static void read_library_controllers_controller_skin(Document.LibraryControllers.Controller.Skin skin, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "source")
                {
                    skin.source = a.Value.Replace("#", string.Empty);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "bind_shape_matrix")
                {
                    Matrix.TryParse(e.Value, out skin.bind_shape_matrix);
                }
                if (e.Name.LocalName == "source")
                {
                    Document.LibraryControllers.Controller.Skin.Source source = new LibraryControllers.Controller.Skin.Source();

                    read_library_controllers_controller_skin_source(source, e);

                    skin.sourceList.Add(source);
                }
                if (e.Name.LocalName == "joints")
                {
                    Document.LibraryControllers.Controller.Skin.Joints joints = new LibraryControllers.Controller.Skin.Joints();

                    read_library_controllers_controller_skin_joints(joints, e);

                    skin.joints = joints;
                }
                if (e.Name.LocalName == "vertex_weights")
                {
                    Document.LibraryControllers.Controller.Skin.VertexWeights vertex_weights = new LibraryControllers.Controller.Skin.VertexWeights();

                    read_library_controllers_controller_skin_vertex_weights(vertex_weights, e);

                    skin.vertex_weights = vertex_weights;
                }
            }
        }
        private static void read_library_controllers_controller(Document.LibraryControllers.Controller controller, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    controller.id = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "skin")
                {
                    Document.LibraryControllers.Controller.Skin skin = new LibraryControllers.Controller.Skin();

                    read_library_controllers_controller_skin(skin, e);

                    controller.skin = skin;
                }
            }
        }
        private static void read_library_controllers(Document.LibraryControllers library_controllers, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if(e.Name.LocalName == "controller") 
                {
                    LibraryControllers.Controller controller = new LibraryControllers.Controller();

                    read_library_controllers_controller(controller, e);

                    library_controllers.controllers.Add(controller);
                }
            }
        }
        #endregion

        #region Read Library Visual Scenes

        private static void read_library_visual_scenes_visual_scene_node_instance_geometry_bind_material_technique_common_instance_material(Document.LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial.TechniqueCommon.InstanceMaterial instance_material, XElement element)
        { 
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "symbol")
                {
                    instance_material.symbol = a.Value;
                }

                if (a.Name == "target")
                {
                    instance_material.target = a.Value.Replace("#", string.Empty);
                }
            }
        }
        private static void read_library_visual_scenes_visual_scene_node_instance_geometry_bind_material_technique_common(Document.LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial.TechniqueCommon technique_common, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "instance_material")
                {
                    Document.LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial.TechniqueCommon.InstanceMaterial instance_material = new LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial.TechniqueCommon.InstanceMaterial();

                    read_library_visual_scenes_visual_scene_node_instance_geometry_bind_material_technique_common_instance_material(instance_material, e);

                    technique_common.instance_material = instance_material;
                }
            }
        }
        private static void read_library_visual_scenes_visual_scene_node_instance_geometry_bind_material(Document.LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial bind_material, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "technique_common")
                {
                    Document.LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial.TechniqueCommon technique_common = new LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial.TechniqueCommon();

                    read_library_visual_scenes_visual_scene_node_instance_geometry_bind_material_technique_common(technique_common, e);

                    bind_material.technique_common = technique_common;
                }
            }
        }
        private static void read_library_visual_scenes_visual_scene_node_instance_geometry(Document.LibraryVisualScenes.VisualScene.Node.InstanceGeometry instance_geometry, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "url")
                {
                    instance_geometry.url = a.Value.Replace("#", string.Empty);
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "bind_material")
                {
                    Document.LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial bind_material = new LibraryVisualScenes.VisualScene.Node.InstanceGeometry.BindMaterial();

                    read_library_visual_scenes_visual_scene_node_instance_geometry_bind_material(bind_material, e);

                    instance_geometry.bind_material = bind_material;
                }
            }
        }
        private static void read_library_visual_scenes_visual_scene_node_instance_camera(Document.LibraryVisualScenes.VisualScene.Node.InstanceCamera instance_camera, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "url")
                {
                    instance_camera.url = a.Value.Replace("#", string.Empty);
                }
            }
        }
        private static void read_library_visual_scenes_visual_scene_node_instance_light(Document.LibraryVisualScenes.VisualScene.Node.InstanceLight instance_light, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "url")
                {
                    instance_light.url = a.Value.Replace("#", string.Empty);
                }
            }
        }
        private static void read_library_visual_scenes_visual_scene_node(Document.LibraryVisualScenes.VisualScene.Node node, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    node.id = a.Value;
                }

                if (a.Name == "sid")
                {
                    node.sid = a.Value;
                }

                if (a.Name == "name")
                {
                    node.name = a.Value;
                }

                if (a.Name == "type")
                {
                    node.type = a.Value;
                }
            }
            
            node.elementType = "transform";

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "matrix")
                {
                    Matrix.TryParse(e.Value, out node.matrix);
                }

                if (e.Name.LocalName == "translate")
                {
                    Vector3 v = Vector3.Zero;

                    Vector3.TryParse(e.Value, out v);

                    node.matrix = Matrix.Translate(v) * node.matrix;
                }

                if (e.Name.LocalName == "rotate")
                {
                    Vector4 v = Vector4.Zero;

                    Vector4.TryParse(e.Value, out v);

                    node.matrix = Matrix.CreateFromAxisAngle(new Vector3(v.X,
                                                                          v.Y,
                                                                          v.Z),
                                                               MathHelper.ToRadians(v.W)) * node.matrix;
                }

                if (e.Name.LocalName == "scale")
                {
                    Vector3 v = Vector3.Zero;

                    Vector3.TryParse(e.Value, out v);

                    node.matrix = Matrix.CreateScale(v) * node.matrix;
                }

                if (e.Name.LocalName == "instance_geometry")
                {
                    node.elementType = "geometry";

                    Document.LibraryVisualScenes.VisualScene.Node.InstanceGeometry instance_geometry = new LibraryVisualScenes.VisualScene.Node.InstanceGeometry();

                    read_library_visual_scenes_visual_scene_node_instance_geometry(instance_geometry, e);

                    node.instance_geometry = instance_geometry;
                }

                if (e.Name.LocalName == "instance_camera")
                {
                    node.elementType = "camera";

                    Document.LibraryVisualScenes.VisualScene.Node.InstanceCamera instance_camera = new LibraryVisualScenes.VisualScene.Node.InstanceCamera();

                    read_library_visual_scenes_visual_scene_node_instance_camera(instance_camera, e);

                    node.instance_camera = instance_camera;
                }

                if (e.Name.LocalName == "instance_light")
                {
                    node.elementType = "light";

                    Document.LibraryVisualScenes.VisualScene.Node.InstanceLight instance_light = new LibraryVisualScenes.VisualScene.Node.InstanceLight();

                    read_library_visual_scenes_visual_scene_node_instance_light(instance_light, e);

                    node.instance_light = instance_light;
                }

                if (e.Name.LocalName == "node")
                {
                    Document.LibraryVisualScenes.VisualScene.Node n = new LibraryVisualScenes.VisualScene.Node();

                    read_library_visual_scenes_visual_scene_node(n, e);

                    node.nodes.Add(n);
                }
            }
        }
        private static void read_library_visual_scenes_visual_scene(Document.LibraryVisualScenes.VisualScene visual_scene, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "id")
                {
                    visual_scene.id = a.Value;
                }

                if (a.Name == "name")
                {
                    visual_scene.name = a.Value;
                }
            }

            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "node")
                {
                    Document.LibraryVisualScenes.VisualScene.Node node = new Document.LibraryVisualScenes.VisualScene.Node();

                    read_library_visual_scenes_visual_scene_node(node, e);

                    visual_scene.nodes.Add(node);
                }
               
            }
        }
        private static void read_library_visual_scenes(Document.LibraryVisualScenes library_visual_scenes, XElement element)
        {
            foreach (XElement e in element.Elements())
            {
                if (e.Name.LocalName == "visual_scene")
                {
                    Document.LibraryVisualScenes.VisualScene visual_scene = new LibraryVisualScenes.VisualScene();

                    read_library_visual_scenes_visual_scene(visual_scene, e);

                    library_visual_scenes.visual_scene = visual_scene;
                }
            }
        }

        #endregion

        #region Read Scene

        private static void read_scene_instance_visual_scene(Document.Scene.InstanceVisualScene instance_visual_scene, XElement element)
        {
            foreach (XAttribute a in element.Attributes())
            {
                if (a.Name == "url")
                {
                    instance_visual_scene.url = a.Value;
                }
            }
        }
        private static void read_scene(Document.Scene scene, XElement element)
        {
            foreach(XElement e in element.Elements())
            {
                if (e.Name.LocalName == "instance_visual_scene")
                {
                    Document.Scene.InstanceVisualScene instance_visual_scene = new Scene.InstanceVisualScene();

                    read_scene_instance_visual_scene(instance_visual_scene, e);

                    scene.instance_visual_scene = instance_visual_scene;
                }
            }
        }

        #endregion

        /// <summary>
        /// Loads a raw representation of the collada document. 
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static Document Load(string filename)
        {
            XDocument document = XDocument.Load(filename, LoadOptions.PreserveWhitespace);
            Document   collada  = new Document();

            if(document.Root.Attribute("version") != null)
            collada.version    = document.Root.Attribute("version").Value;

            if (document.Root.Attribute("xmlns") != null)
            collada.xmlns      = document.Root.Attribute("xmlns").Value;
          
            foreach (XElement e in document.Root.Elements())
            {
                if (e.Name.LocalName == "asset")
                {
                    Document.Asset asset = new Document.Asset();

                    read_asset(asset, e);

                    collada.asset = asset;
                }

                if (e.Name.LocalName == "library_animations")
                {
                    Document.LibraryAnimations library_animations = new Document.LibraryAnimations();

                    read_library_animations(library_animations, e);

                    collada.library_animations = library_animations;
                }

                if (e.Name.LocalName == "library_animation_clips")
                {
                    Document.LibraryAnimationClips library_animation_clips = new Document.LibraryAnimationClips();

                    read_library_animation_clips(library_animation_clips, e);

                    collada.library_animation_clips = library_animation_clips;
                }

                if (e.Name.LocalName == "library_materials")
                {
                    Document.LibraryMaterials library_materials = new Document.LibraryMaterials();

                    read_library_materials(library_materials, e);

                    collada.library_materials = library_materials;
                }

                if (e.Name.LocalName == "library_cameras")
                {
                    Document.LibraryCameras library_cameras = new Document.LibraryCameras();

                    read_library_cameras(library_cameras, e);

                    collada.library_cameras = library_cameras;
                }

                if (e.Name.LocalName == "library_lights")
                {
                    Document.LibraryLights library_lights = new Document.LibraryLights();

                    read_library_lights(library_lights, e);
                    
                    collada.library_lights = library_lights;
                }

                if (e.Name.LocalName == "library_images")
                {
                    Document.LibraryImages library_images = new Document.LibraryImages();

                    read_library_images(library_images, e);

                    collada.library_images = library_images;
                }

                if (e.Name.LocalName == "library_effects")
                {
                    Document.LibraryEffects library_effects = new Document.LibraryEffects();

                    read_library_effects(library_effects, e);

                    collada.library_effects = library_effects;
                }

                if (e.Name.LocalName == "library_geometries")
                {
                    Document.LibraryGeometries library_geometries = new Document.LibraryGeometries();

                    read_library_geometries(library_geometries, e);

                    collada.library_geometries = library_geometries;
                }

                if (e.Name.LocalName == "library_controllers")
                {
                    Document.LibraryControllers library_controllers = new Document.LibraryControllers();

                    read_library_controllers(library_controllers, e);

                    collada.library_controllers = library_controllers;
                }

                if (e.Name.LocalName == "library_visual_scenes")
                {
                    Document.LibraryVisualScenes library_visual_scenes = new Document.LibraryVisualScenes();

                    read_library_visual_scenes(library_visual_scenes, e);

                    collada.library_visual_scenes = library_visual_scenes;
                }

                if (e.Name.LocalName == "scene")
                {
                    Document.Scene scene = new Document.Scene();

                    read_scene(scene, e);

                    collada.scene = scene;
                }
            }

            GC.Collect();

            return collada;
        }
    }
}
